;
;  PROGRAM:  DEVICE2
;  AUTHOR:  RICHARD CONN
;  VERSION:  1.3
;  DATE:  6 Jan 83
;  PREVIOUS VERSION:  1.0 (29 Dec 82), 1.1 (2 Jan 83), 1.2 (5 Jan 83)
;
VERS	EQU	13

;
;	This program is Copyright (c) 1982, 1983 by Richard Conn
;	All Rights Reserved
;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;	The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;


;
;	DEVICE is a program which enables the user to manipulate the
; extended ZCPR2 redirectable device drivers.  It allows the user to
; perform the following functions:
;
;		o Display the Names of the Current Devices
;		o Set One or More of the Current Devices
;		o Ask for Help
;
;	The format of the DEVICE command is:
;
;		DEVICE or DEVICE //		<-- Ask for Help
;		DEVICE command,command,command ...	<-- Issue Commands
;
; where "command" may take the following forms:
;
;		DISPLAY ALL	<-- Display Names of All Devices
;		DISPLAY CON	<-- Display Names of Consoles
;		DISPLAY LST	<-- Display Names of Printers
;		DISPLAY RDR	<-- Display Names of Readers
;		DISPLAY PUN	<-- Display Names of Punches
;
;		CON:=name	<-- Select Console
;		LST:=name	<-- Select Printer
;		RDR:=name	<-- Select Reader
;		PUN:=name	<-- Select Punch
;

;
;  Constants
;
tbuff	equ	80h
cr	equ	0dh
lf	equ	0ah

;
;  SYSLIB Routines
;
	ext	cin,cout,pstr,print,cline,bbline

;
;  Branch to Start of Program
;
	jmp	start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	0FFH	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	000H	; EXTERNAL PATH?
MCREQD:
	DB	000H	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	000H	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	000H	; CURRENT INDIC AND DMA?
NDREQD:
	DB	000H	; NAMED DIRECTORIES?
Z2CLASS:
	DB	1	; CLASS 1
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Other Parameter Data
;
drvadr:
	dw	0	; Address of I/O Drivers

;
;  Start of Program
;
start:
	call	print
	db	'DEVICE2, Version '
	db	(vers/10)+'0','.',(vers mod 10)+'0',0

	lhld	drvadr	;check for initialization
	mov	a,h
	ora	l	;must NOT be zero
	jnz	start0
	call	print
	db	cr,lf,'DEVICE NOT Initialized with I/O Base -- Aborting',0
	ret

start0:
	call	status	;check for drivers
	jnz	start1
	call	print
	db	cr,lf,'Redirection Not Supported -- Aborting',0
	ret

start1:
	lxi	h,tbuff	;pt to input buffer
	call	cline	;extract and save command line
	call	sblank	;skip to non-blank
	ora	a	;EOL?
	jz	command	;command mode
	cpi	'/'	;help?
	jnz	docmd	;run command subroutine

;
;  Print Help Message
;
help:
	call	print
	db	cr,lf,'	DEVICE is a program which enables the user to'
	db	cr,lf,'manipulate the extended ZCPR2 redirectable device'
	db	cr,lf,'drivers.  It allows the user to perform the following'
	db	cr,lf,'functions:'
	db	cr,lf,'		Display the Names of the Current Devices'
	db	cr,lf,'		Set One or More of the Current Devices'
	db	cr,lf,'	The format of the DEVICE command is:'
	db	cr,lf,'		DEVICE				'
	db	'<-- Enter Interactive Mode'
	db	cr,lf,'		DEVICE //			'
	db	'<-- Ask for Help'
	db	cr,lf,'		DEVICE '
help1:
	db	'Command,Command, ... 	'
	db	'<-- Issue Commands'
	db	cr,lf,'where "command" may take the following forms:'
	db	cr,lf,'		DISPLAY=ALL	'
	db	'<-- Display Names of All Devices'
	db	cr,lf,'		DISPLAY=CON	'
	db	'<-- Display Names of Consoles'
	db	cr,lf,'		DISPLAY=LST	'
	db	'<-- Display Names of Printers'
	db	cr,lf,'		DISPLAY=RDR	'
	db	'<-- Display Names of Readers'
	db	cr,lf,'		DISPLAY=PUN	'
	db	'<-- Display Names of Punches'
	db	cr,lf
	db	cr,lf,'		CON:=name	<-- Select Console'
	db	cr,lf,'		LST:=name	<-- Select Printer'
	db	cr,lf,'		RDR:=name	<-- Select Reader'
	db	cr,lf,'		PUN:=name	<-- Select Punch'
	db	cr,lf,0
	ret
;
;  Skip to Non-Blank Routine
;
sblank:
	mov	a,m	;get char
	inx	h	;pt to next
	cpi	' '	;blank?
	jz	sblank	;continue if so
	dcx	h	;pt to non-blank
	ret

;
;  Skip until a delimiter encountered
;
sdelm:
	mov	a,m	;get char
	inx	h	;pt to next
	cpi	' '+1	;<SP> or less?
	rc
	cpi	'='
	rz
	cpi	','
	rz
	cpi	';'
	rz
	jmp	sdelm

;
;  COMMAND -- This is an interactive mainline which allows user input,
;    runs command lines via DOCMD, and permits Help and Comments
;
command:
	call	print
	db	cr,lf,'DEVICE2 Interactive Command System'
	db	cr,lf,'Type ? and Strike RETURN for Help'
	db	0
cloop:
	call	print
	db	cr,lf,'DEVICE2 Command? ',0
	mvi	a,0ffh	;capitalize
	call	bbline
	call	sblank	;skip to non-blank
	mov	a,m	;empty line?
	ora	a	;0=yes
	jz	cloop
	cpi	'?'	;help?
	jz	chelp
	cpi	';'	;comment?
	jz	cloop
	cpi	'X'	;done?
	rz
	call	docmd	;run command line
	jmp	cloop
chelp:
	call	print
	db	cr,lf,'DEVICE2 Commands are of the form:',cr,lf,0
	lxi	h,help1
	call	pstr
	call	print
	db	cr,lf,'A command line beginning with a semicolon (;) is a'
	db	' comment.'
	db	cr,lf,'The X Command Exits DEVICE2.'
	db	cr,lf,0
	jmp	cloop

;
;  DOCMD -- This subroutine processes the command line pted to by HL.
;    It is the Main Line if a DEVICE command line is given, it is just
;    a subroutine if the user is in interactive mode.
;
docmd:
	call	docmd1	;do first command
	call	sdelm	;skip to delim
	cpi	','	;another command?
	jz	docmd
	cpi	';'	;another also?
	jz	docmd
	ret
docmd1:
	mov	a,m	;get command letter
	cpi	'C'	;console assignment?
	jz	docon
	cpi	'D'	;display?
	jz	dodisp
	cpi	'L'	;LST:?
	jz	dolst
	cpi	'P'	;PUN:?
	jz	dopun
	cpi	'R'	;RDR:?
	jz	dordr
cerr:
	call	print
	db	cr,lf,'Command Error at -- ',0
	call	pstr	;print rest
	ret

;
;  Do LST: Assignment
;
dolst:
	mvi	a,3	;select LST:
	jmp	assign

;
;  Do PUN: Assignment
;
dopun:
	mvi	a,2	;select PUN:
	jmp	assign

;
;  Do RDR: Assignment
;
dordr:
	mvi	a,1	;select RDR:
	jmp	assign

;
;  Do CON: Assignment
;
docon:
	mvi	a,0	;select console
;
;  Do Assignment in General
;
assign:
	mov	b,a	;save A in B
	push	b	;save BC
	call	sdelm	;skip to delimiter
	pop	b	;get BC
	cpi	' '
	jz	asgn0
	cpi	'='
	jnz	cerr
asgn0:
	mov	a,b	;get A back
	sta	logical	;save logical device number
	shld	name	;save ptr to mnemonic
	mov	b,a	;number in B
	inr	b	;add 1 for offset
	call	status	;get device status
	dcx	h	;pt to previous
	dcx	h
asgn1:
	inx	h	;pt to next
	inx	h
	dcr	b	;count down
	jnz	asgn1
	mov	c,m	;get number of devices in C
	mov	a,c	;check for value of zero
	ora	a
	jnz	asgn2
	lhld	name	;pt to error name
	jmp	cerr
asgn2:
	lda	logical	;get logical device number
	mov	b,a	;... in B
	push	b	;save device count
	dcr	c	;pt to previous
	call	namer	;get name
	xchg		;name pted to by DE
	lhld	name	;user's name pted to by HL
asgn3:
	ldax	d	;get name of device
	cpi	' '+1	;done?
	jc	asgn3a
	cmp	m	;compare to user
	jnz	asgn4
	inx	h	;pt to next
	inx	d
	jmp	asgn3
asgn3a:
	mov	a,m	;get user
	cpi	' '+1	;done?
	jc	asgn3b
	cpi	','	;done?
	jnz	asgn4
asgn3b:
	pop	b	;match -- C-1 is selected device
	dcr	c	;decrement
	call	select	;select device
	lhld	name	;pt to name for scan continuation
	ret
asgn4:
	pop	b	;count down
	dcr	c	;count down
	jnz	asgn2	;continue
	lhld	name	;pt to invalid name
	call	print
	db	cr,lf,'Invalid Name Assignment at -- ',0
	call	pstr
	lhld	name	;pt to name for scan continuation
	ret

;
;  Display Devices and Assignments
;
dodisp:
	call	sdelm	;skip to delimiter
	ora	a	;none=all
	jz	dispall
	mov	a,m	;get char after delimiter
	cpi	'A'	;all?
	jz	dispall
	cpi	'C'	;CON:
	jz	dispcon
	cpi	'L'	;LST:
	jz	displst
	cpi	'P'	;PUN:
	jz	disppun
	cpi	'R'	;RDR:
	jz	disprdr
	jmp	cerr
dispall:
	call	dispcon	;successive displays
	call	disprdr
	call	print
	db	cr,lf,'Strike Any Key to Continue -- ',0
	call	cin
	call	disppun
	jmp	displst
dispcon:
	call	print
	db	cr,lf,cr,lf,'CON: Devices --',0
	mvi	a,0	;select CON:
	call	disp
	jmp	current
displst:
	call	print
	db	cr,lf,cr,lf,'LST: Devices --',0
	mvi	a,3	;select LST:
	call	disp
	jmp	current
disprdr:
	call	print
	db	cr,lf,cr,lf,'RDR: Devices --',0
	mvi	a,1	;select RDR:
	call	disp
	jmp	current
disppun:
	call	print
	db	cr,lf,cr,lf,'PUN: Devices --',0
	mvi	a,2	;select PUN:
	call	disp
;
;  Print Name of Current Device
;
current:
	push	h	;save ptr
	mov	b,a	;save number in B
	push	b	;save B
	call	print
	db	cr,lf,'  Current Assignment: ',0
	push	b	;save B
	call	status	;get status
	pop	b	;get B
	inr	b	;add 1 for offset
	dcx	h	;back up
curr:
	inx	h	;pt to next
	inx	h
	dcr	b	;count down
	jnz	curr
	pop	b	;get logical number in B
	mov	c,m	;get physical number in C
	call	pname0	;print first part of name only
	pop	h	;get ptr
	ret
;
;  Print Names of All Physical Devices for a Logical Device
;
disp:
	push	h	;save char ptr
	push	psw	;save device number
	mov	b,a	;logical device in B
	push	b	;save for later
	push	b	;save it
	call	status	;get status report
	pop	b	;get logical device number
	inr	b	;add 1 for offset
	dcx	h	;back up
	dcx	h
disp1:
	inx	h	;pt to next
	inx	h
	dcr	b	;count down
	jnz	disp1
	pop	b	;get B back
	mov	c,m	;get count of devices
disp2:
	push	b	;save values
	dcr	c	;pt to next name
	call	print
	db	cr,lf,'	',0
	call	pnamer	;print name (B=logical, C=physical)
	pop	b	;get count
	dcr	c	;count down
	jnz	disp2
	pop	psw
	pop	h
	ret
;
;  Routine to Print Name of Selected Device
;	B=logical number, C=physical number
;
pnamer:
	push	b	;save BC
	call	pname0	;print first part of name
	call	print	;print separator
	db	' - ',0
	call	pstr	;print rest as string
	pop	b	;restore BC
	ret
;
;  Print first part of selected device name
;
pname0:
	call	namer	;get ptr to string
	mvi	b,8	;at most 8 chars
pname1:
	mov	a,m	;get char
	inx	h	;pt to next char
	cpi	' '	;end of name?
	jz	pname2
	call	cout	;print char
	dcr	b	;count down
	jnz	pname1
	ret
pname2:
	mvi	a,' '	;print spaces
	call	cout
	dcr	b	;count down
	jnz	pname2
	ret

;
;  Basic Interface Routines
;
status:
	lxi	d,0	;Offset 0
runit:
	lhld	drvadr	;device driver base
	dad	d
	pchl
select:
	lxi	d,3	;Offset 3
	jmp	runit
namer:
	lxi	d,6	;Offset 6
	jmp	runit

;
;  Buffers
;
logical:
	ds	1	;Logical Device Number
name:
	ds	2	;Pointer to User-Supplied Name

	end
